﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using CloudShot.Controls;
using CloudShot.Logic;
using CloudShot.Utils;

namespace CloudShot.Editor.CanvasFigures
{
  public sealed class CanvasCrop : CanvasRectangle
  {
    private readonly Pen _borderPen;
    public bool IsSelectionState { get; set; }
    public bool IsDragOnlyByEdges { get; set; }
    public Rectangle CanvasBounds { get; set; }
    public HtmlHint Hint { get; private set; }
    public bool DrawHint { get; set; }


    public CanvasCrop(HtmlHint hint)
      : base(0, 0, 0, 0)
    {
      TrackerColor = Color.LightGray;
      //TrackerSize = 6;

      TrackerType = TrackerType.Square;
      IsShowSize = true;
      IsDragOnlyByEdges = true;

      BorderColor = Color.FromArgb(73, 73, 73);
      BorderWidth = 1;
      _borderPen = CreateBorderPen();

      Hint = hint;
      DrawHint = true;
    }

    /// <summary>
    ///   Draw rectangle
    /// </summary>
    /// <param name="graphics"></param>
    public override void Draw(Graphics graphics)
    {
      Rectangle rect = Rectangle.GetNormalizedRectangle();

      using (var backBrush = CreateBackBrush())
      using (var path = new GraphicsPath())
      {
        path.AddRectangle(rect);// add the desired path
        path.AddRectangle(CanvasBounds);// add the rectangle to invert the inside  
        
        graphics.FillPath(backBrush, path);
        graphics.DrawRectangle(_borderPen, rect);
      }
    }

    /// <summary>
    ///   Hit test.
    ///   Return value: -1 - no hit
    ///   0 - hit anywhere
    ///   > 1 - handle number
    /// </summary>
    /// <param name="point"></param>
    /// <returns></returns>
    public override int HitTest(Point point)
    {
      int result = base.HitTest(point);

      if (!IsDragOnlyByEdges || result > 0)
        return result;

      const int hoverRadius = 5;

      Rectangle rect = Rectangle.GetNormalizedRectangle();

      if (IsInInterval(point.X, rect.Left - hoverRadius, rect.Left + hoverRadius))
        return 0;

      if (IsInInterval(point.X, rect.Right - hoverRadius, rect.Right + hoverRadius))
        return 0;

      if (IsInInterval(point.Y, rect.Top - hoverRadius, rect.Top + hoverRadius))
        return 0;

      if (IsInInterval(point.Y, rect.Bottom - hoverRadius, rect.Bottom + hoverRadius))
        return 0;

      return -1;
    }

    public override Cursor GetHandleCursor(int handleNumber)
    {
      if (handleNumber == VertexType.None)
        return AppCursors.CropOverCursor;

      return base.GetHandleCursor(handleNumber);
    }

    public override void DrawMarkup(Graphics graphics, Rectangle[] screens)
    {
      //TODO move this code to Move/resize/show and hide hint
      if (DrawHint)
      {
        Rectangle currentScreen = GetCurrentScreen(screens, VertexType.Center);
        Hint.PerformLayout(currentScreen);
        Hint.CropOverlaps = Hint.GetBoundingBox().IntersectsWith(Rectangle);

        Hint.Draw(graphics); 
      }

      base.DrawMarkup(graphics, screens);
    }



    public override Rectangle GetBoundingBox()
    {
      //hint bounding box is required for moving/resizing crop
      Rectangle rect = base.GetBoundingBox();
      return Hint.IsHintVisibleForBoundingBox ? Rectangle.Union(rect, Hint.GetBoundingBox()) : rect;
    }

    protected override void DrawSizeControl(Graphics graphics, Rectangle[] screens)
    {
      bool showLocation = Rectangle.Size.IsEmpty;
      int handle = showLocation ? VertexType.RightBottom : CurrentDragHandle;
      Rectangle currentScreen = GetCurrentScreen(screens, handle);
      Size value = showLocation ? GetRelativeLocationToScreen(currentScreen, Rectangle.Location): Rectangle.Size;

      SizeControl.Draw(graphics, Rectangle, value, currentScreen, handle);
    }

    private Size GetRelativeLocationToScreen(Rectangle currentScreen, Point location)
    {
      return new Size(location.X - currentScreen.X, location.Y - currentScreen.Y);
    }


    protected override CanvasObject CloneIntrenal()
    {
      throw new NotImplementedException("crop shouldnt be cloned");
    }

    private static bool IsInInterval(int value, int start, int end)
    {
      return value >= start && value <= end;
    }
  }
}